package com.wuwei.business.service.impl;

import java.security.Security;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.alibaba.fastjson.JSON;
import com.wuwei.business.Constant.CarConstant;
import com.wuwei.business.Dto.CarDto;
import com.wuwei.business.VO.RentVo;
import com.wuwei.business.domain.BusRent;
import com.wuwei.business.mapper.BusRentMapper;
import com.wuwei.business.utils.SnUtil;
import com.wuwei.common.core.domain.entity.SysDept;
import com.wuwei.common.core.domain.model.LoginUser;
import com.wuwei.common.utils.DateUtils;
import com.wuwei.business.domain.BusAttachment;
import com.wuwei.business.mapper.BusAttachmentMapper;
import com.wuwei.common.utils.SecurityUtils;
import com.wuwei.common.utils.bean.BeanUtils;
import com.wuwei.system.service.ISysDeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.wuwei.business.mapper.BusCarMapper;
import com.wuwei.business.domain.BusCar;
import com.wuwei.business.service.IBusCarService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

/**
 * 车辆Service业务层处理
 * 
 * @author wuwei
 * @date 2021-12-29
 */
@Service
@Slf4j
public class BusCarServiceImpl implements IBusCarService {
    @Autowired
    private BusCarMapper busCarMapper;
    @Autowired
    private ISysDeptService sysDeptService;
    @Autowired
    private BusAttachmentMapper attachmentMapper;
    @Autowired
    private SnUtil  snUtil;
    @Autowired
    private BusRentMapper busRentMapper;
    /**
     * 查询车辆
     *
     * @param id 车辆主键
     * @return 车辆
     */
    @Override
    public BusCar selectBusCarById(Long id) {
        return busCarMapper.selectBusCarById(id);
    }

    /**
     * 查询车辆列表
     *
     * @param busCar 车辆
     * @return 车辆
     */
    @Override
    public List<BusCar> selectBusCarList(BusCar busCar) {
        return busCarMapper.selectBusCarList(busCar);
    }

    /**
     * 新增车辆
     *
     * @param busCar 车辆
     * @return 结果
     */
    @Override
    public int insertBusCar(BusCar busCar) {
        busCar.setCreateTime(DateUtils.getNowDate());
        return busCarMapper.insertBusCar(busCar);
    }

    /**
     * 修改车辆
     *
     * @param busCar 车辆
     * @return 结果
     */
    @Override
    public int updateBusCar(BusCar busCar) {
        busCar.setUpdateTime(DateUtils.getNowDate());
        return busCarMapper.updateBusCar(busCar);
    }

    /**
     * 批量删除车辆
     *
     * @param ids 需要删除的车辆主键
     * @return 结果
     */
    @Override
    public int deleteBusCarByIds(Long[] ids) {
        return busCarMapper.deleteBusCarByIds(ids);
    }

    /**
     * 删除车辆信息
     *
     * @param id 车辆主键
     * @return 结果
     */
    @Override
    public int deleteBusCarById(Long id) {
        return busCarMapper.deleteBusCarById(id);
    }

    /**
     * 分页批量查询车辆
     * @param loginUser
     * @param carDto
     * @return
     */
    @Override
    public List<BusCar> getCarPage(LoginUser loginUser, CarDto carDto) {
        return busCarMapper.getCarPage(loginUser, carDto);
    }

    /**
     * 添加车辆
     * @param carDto
     * @param loginUser
     * @return
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int addCar(CarDto carDto, LoginUser loginUser) {
        log.info("添加车辆{}，当前用户id为{}", JSON.toJSONString(carDto), loginUser.getUserId());
        String username = loginUser.getUsername();
        //判断车架号是否存在，不能重复入库
        BusCar car = busCarMapper.selectCarByFrameNum(carDto.getFrameNumber());
        if (!ObjectUtils.isEmpty(car)) {
            //车架号已存在
            throw new IllegalArgumentException("该车辆已存在");
        }
        carDto.setCreateTime(new Date());
        carDto.setUpdateTime(new Date());
        carDto.setCreateBy(username);
        carDto.setUpdateBy(username);
        carDto.setDelFlag(CarConstant.DEL_FLAG_UNDEL);
        //处理部门
        SysDept sysDept = sysDeptService.selectDeptById(carDto.getDeptId());
        carDto.setDeptName(sysDept.getDeptName());
        //新增车
        int i = busCarMapper.insertBusCar(carDto);
        if (i > 0) {
            handlerCarImg(carDto, username);
        }
        return i;
    }

    /**
     * 处理车辆图片
     *
     * @param carDto
     * @param username
     */
    private void handlerCarImg(CarDto carDto, String username) {
        // 处理图片
        String carImgs = carDto.getCarImages();
        if (StringUtils.hasText(carImgs)) {
            String[] imgs = {carImgs};
            // 说明图片有路径
            if (carImgs.contains(",")) {
                imgs = carImgs.split(",");
            }
            List<BusAttachment> busAttachments = new ArrayList<>(imgs.length);
            // 按照多个图片来处理
            for (String img : imgs) {
                // 处理文件名称
                String imgName = img.substring(img.lastIndexOf("/") + 1);
                String extName = StringUtils.getFilenameExtension(imgName);
                // 构建者模式 链式编程
                BusAttachment attachment = BusAttachment.builder()
                        .createTime(new Date())
                        .updateTime(new Date())
                        .createBy(username)
                        .updateBy(username)
                        .delFlag(CarConstant.DEL_FLAG_UNDEL)
                        .carNumber(carDto.getCarNumber())
                        .fileName(imgName) // 文件的名称不能重复
                        .fileType(extName)
                        .filePath(img)
                        .build();
                busAttachments.add(attachment);
            }
            attachmentMapper.saveBatch(busAttachments);
        }
    }


    /**
     * 根据id查询单条记录
     * @param id
     * @return
     */
    @Override
    public CarDto getCarInfo(Long id) {
        CarDto carDto = new CarDto();
        //查询
        //通过id回显信息数据
        BusCar car = busCarMapper.selectBusCarById(id);
        //通过id回显图片
        List<String> carImags=attachmentMapper.selectListByCarNum(car.getCarNumber());
        if (!CollectionUtils.isEmpty(carImags)) {
            // 将集合中的条目按照指定的字符拼接   jojning 用逗号拼接

            String carImgsStr = carImags.stream().collect(Collectors.joining(","));
            carDto.setCarImages(carImgsStr);
        }
        // 对象拷贝对象属性转换
        BeanUtils.copyBeanProp(carDto, car);
        return carDto;
    }
    /**
     * 修改车辆信息
     * 1.修改汽车表
     * 2.处理图片
     * 将旧的图片删掉 再插入新的图片
     *
     * @param carDto
     * @param loginUser
     * @return
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int updateCar(CarDto carDto, LoginUser loginUser) {
        log.info("修改车辆信息{}，当前用户id为{}", JSON.toJSONString(carDto), loginUser.getUserId());
        String username = loginUser.getUsername();
        BusCar car = busCarMapper.selectCarByFrameNum(carDto.getFrameNumber());
        carDto.setUpdateTime(new Date());
        carDto.setUpdateBy(username);
        //处理部门
        SysDept sysDept = sysDeptService.selectDeptById(carDto.getDeptId());
        carDto.setDeptName(sysDept.getDeptName());
        //修改车
        int i = busCarMapper.updateBusCar(carDto);
        if (i > 0) {
            //删除原来的图片添加新加的图片 省去判断操作
           attachmentMapper.delImgByCarNum(carDto.getCarNumber(),username);
           handlerCarImg(carDto,username);
        }
        return i;
    }
    /**
     * 根据车辆ids删除车辆
     * 0.如果车辆正在出租 那么需要提示不能删除  (因为可以批量操作 需要做批量判断)
     * 1.修改车辆表 del_flag = 1
     * 2.修改图片表 将del_flag = 1
     *
     * @param ids
     * @param loginUser
     * @return
     */
    @Override
    public int delCar(List<Long> ids, LoginUser loginUser) {
        log.info("删除车辆id为{}，当前用户id为{}", JSON.toJSONString(ids), loginUser.getUserId());
        String username = loginUser.getUsername();
        //判断有已出租就不能删
        List<BusCar> busCarList=busCarMapper.selectCarByIds(ids);
        //Stream().filter 过滤 按照自己的规则  .count 表数量 聚合
        long count = busCarList.stream().filter(busCar -> busCar.getStatus().equals(CarConstant.CAR_IS_RENT))
                .count();
        if (count>0){
            throw  new IllegalArgumentException("有车辆未归还不能删除");
        }
        //删除
       int i= busCarMapper.delCarBatch(ids,loginUser);
       if (i>0){
            // 处理图片
            // 拿到车牌号   BusCar::getCarNumber  == BusCar->BusCar.getcarNumber()
            List<String> carNums = busCarList.stream().map((BusCar)->BusCar.getCarNumber())
                    .collect(Collectors.toList());
            // 批量修改图片状态
            attachmentMapper.delImgByCarNumBatch(carNums, username);
        }
        return i;
    }
    /**
     * 去租车(将租车信息展示出来) 回溯
     * 1.生成一个出租单号
     * 订单号 (雪花算法)
     * 唯一
     * 最好携带时间戳  （可以回溯 可以根据时间戳反向计算出时间 ）
     * 最好单调递增 后面一个值比前面大即可 不是说大1位  （方便查询  时间复杂度降低 ）
     *
     * @param carId
     * @return
     */
    @Override
    public RentVo toRent(Long carId)  {
        RentVo rentVo = new RentVo();
        String sn = snUtil.createSn(CarConstant.RENT_PREFIX);
        BusCar busCar = busCarMapper.selectBusCarById(carId);
        //copyBeanProp就是用第二个值往第一个里面赋   类似于把buscar里面的get出来 set到rentVO中
        BeanUtils.copyBeanProp(rentVo,busCar);
        String username = SecurityUtils.getUsername();
        rentVo.setRentprice(busCar.getRentprice());
        rentVo.setOpername(username);
        rentVo.setRentSn(sn);
        return rentVo;
    }

    /**
     * 做租车业务
     * synchronized加锁
     *
     * @param rentVo
     * @param loginUser 当前用户
     * @return
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean realDoRent(RentVo rentVo, LoginUser loginUser) {
        log.info("租车{}，当前用户id为{}", JSON.toJSONString(rentVo), loginUser.getUserId());
        // 同一时刻 只有一个线程来操作下面的代码块 jvm  entrySet  waitSet
        synchronized (this) {
            // 先查询车辆状态 判断
            BusCar car = busCarMapper.selectCarByFrameNum(rentVo.getFrameNumber());
            //有没有出租
            if (car.getStatus().equals(CarConstant.CAR_IS_RENT)) {
                throw new IllegalArgumentException("该车辆已经出租了");
            }
            String username = loginUser.getUsername();
            BusRent busRent = new BusRent();
            BeanUtils.copyBeanProp(busRent, rentVo);
            //busRent其他的字段补充
            busRent.setRentprice(rentVo.getRentprice());
            busRent.setCreateTime(new Date());
            busRent.setDelFlag(CarConstant.DEL_FLAG_UNDEL);
            busRent.setCreateBy(username);
            busRent.setUpdateBy(username);
            busRent.setUpdateTime(new Date());
            // 处理部门
            busRent.setDeptId(car.getDeptId());
            // 设置车辆未归还
            busRent.setRentStatus(CarConstant.CAR_NOT_REBACK);
            // 插入租车表
            int i = busRentMapper.insertSelective(busRent);
            if (i > 0) {
                // 修改车辆状态
                car.setStatus(CarConstant.CAR_IS_RENT);
                car.setUpdateTime(new Date());
                car.setUpdateBy(username);
                int k = busCarMapper.updateBusCar(car);
                if (k > 0) {
                    return true;
                }
            }
        }
        throw new IllegalArgumentException("车辆出租失败，请重新尝试");
    }
}